package com.etone.smartAudit.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.etone.smartAudit.commService.CommPUumOrganizationinfoService;
import com.etone.smartAudit.commService.CommPUumUserinfoService;
import com.etone.smartAudit.domain.Admin;
import com.etone.smartAudit.domain.PUumOrganizationinfo;
import com.etone.smartAudit.domain.PUumUserinfo;
import com.etone.smartAudit.domain.work.*;
import com.etone.smartAudit.enums.WorkRectifyType;
import com.etone.smartAudit.error.CustomParameterizedException;
import com.etone.smartAudit.mapper.*;
import com.etone.smartAudit.utils.DateUtil;
import com.etone.smartAudit.utils.Excel.ExcelUtil;
import com.etone.smartAudit.utils.ObjectUtil;
import com.etone.smartAudit.vo.PagerVO;
import com.etone.smartAudit.vo.city.CityVO;
import com.etone.smartAudit.vo.workOrder.WorkCountReportVO;
import com.etone.smartAudit.vo.workOrder.WorkOrderRectifyVO;
import com.etone.smartAudit.vo.workOrder.WorkRectifyCountVO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author ：张任豪
 * @date ：2022/3/9 17:05
 * @description：
 */
@AllArgsConstructor
@Service
public class WorkOrderRectifyService {

    private WorkCountCityService workCountCityService;

    private WorkCountProvinceService workCountProvinceService;

    private WorkCountProjectService workCountProjectService;

    private CommPUumUserinfoService pUumUserinfoService;

    private CommPUumOrganizationinfoService commPUumOrganizationinfoService;

    private WorkOrderMapper workOrderMapper;

    private WorkAuditLogMapper workAuditLogMapper;

    private WorkRectifyMapper workRectifyMapper;

    private WorkRectifyCheckMapper workRectifyCheckMapper;

    private CityService cityService;

    /**
     * 风险整改列表
     *
     * @param page
     * @param pageSize
     * @param name
     * @param auditUnit
     * @param year
     * @param startDate
     * @param endDate
     * @param status
     * @param isOverdue
     * @param keyword
     * @param auditStart
     * @param auditEnd
     * @param rectifyResult
     * @param admin
     * @return
     */
    public PagerVO<WorkOrderRectifyVO> listWorkOrderRectify(int page, int pageSize, String name, String auditUnit, String year, Date startDate, Date endDate, Integer status, Integer isOverdue, String keyword, Integer auditStart, Integer auditEnd, Integer rectifyResult, Admin admin) {
        //获取登录账户的组织结构信息
        PUumUserinfo pUumUserinfo = pUumUserinfoService.getOne(new QueryWrapper<PUumUserinfo>().eq("userID", admin.getAccount()));
        if (pUumUserinfo == null && !admin.isAdmin()) {
            throw new CustomParameterizedException("你未在port组织结构中,也不是管理员，所有无权访问");
        }
        Page<WorkOrderRectifyVO> doSelectPage = PageHelper.startPage(page, pageSize).doSelectPage(() -> {
            workOrderMapper.listWorkOrderRectify(name, auditUnit, year, startDate, endDate, status, isOverdue,
                    keyword, auditStart, auditEnd, rectifyResult, pUumUserinfo != null ? pUumUserinfo.getDepartmentID() : null,
                    admin.getRoleId()).forEach(vo -> {
                //封装整改反馈信息
                WorkRectify workRectify = getByWorkId(vo.getIntId());
                if (workRectify != null) {
                    vo.setChargeMan(workRectify.getChargeMan());
                    vo.setChargeDept(workRectify.getChargeDept());
                    vo.setChargeRelateMan(workRectify.getChargeRelateMan());
                    vo.setRectifyPlan(workRectify.getRectifyPlan());
                    vo.setRectifyInfo(workRectify.getRectifyInfo());
                    vo.setRemoldFileOriginName(workRectify.getRemoldFileOriginName());
                    vo.setSystemFileOriginName(workRectify.getSystemFileOriginName());
                    vo.setMeasureFileOriginName(workRectify.getMeasureFileOriginName());
                    vo.setPaperFileOriginName(workRectify.getPaperFileOriginName());
                    vo.setRectifyResult(WorkRectifyType.getRemark(workRectify.getRectifyResult()));
                    vo.setFailCause(workRectify.getFailCause());
                    vo.setExpectTime(workRectify.getExpectTime());
                    vo.setIsStartCharge(workRectify.getIsStartCharge() == 0 ? "否" : "是");
                    vo.setChargeResult(workRectify.getChargeResult());
                }
                //封装整改评估
                WorkRectifyCheck rectifyCheck = workRectifyCheckMapper.getByWork(vo.getIntId());
                if (rectifyCheck != null) {
                    vo.setAssessChargeMan(rectifyCheck.getChargeMan());
                    vo.setFirstCheckInfo(rectifyCheck.getFirstCheckInfo());
                    vo.setAssessStartTime(rectifyCheck.getAssessStartTime());
                    vo.setAssessResult(WorkRectifyType.getRemark(rectifyCheck.getAssessResult()));
                    vo.setAssessStartCharge(rectifyCheck.getIsStartCharge() == 0 ? "否" : "是");
                    vo.setAssessChargeResult(rectifyCheck.getChargeResult());
                }
                //封装反馈时间
                WorkAuditLog auditLog = workAuditLogMapper.selectOne(new QueryWrapper<WorkAuditLog>().eq("intWorkId",vo.getIntId()).orderByDesc("dtExecuteTime").last("limit 1"));
                if (auditLog != null) {
                    vo.setFeedBackTime(auditLog.getExecuteTime());
                }
            });
        });
        return PagerVO.of(doSelectPage);
    }


    public WorkRectifyCountVO rectifyCount(Admin admin) {
        //获取登录账户的组织结构信息
        PUumUserinfo pUumUserinfo = pUumUserinfoService.getOne(new QueryWrapper<PUumUserinfo>().eq("userID", admin.getAccount()));
        if (pUumUserinfo == null && !admin.isAdmin()) {
            throw new CustomParameterizedException("你未在port组织结构中,也不是管理员，所有无权访问");
        }
        HashMap<String, Object> countRectifyRate = workOrderMapper.countRectifyRate();
        if (countRectifyRate == null) {
            return WorkRectifyCountVO.builder().finish(0).inTimeRate(0.0)
                    .reportedRate(0.0).effectiveRectify(0).rectifyRate(0.0).overdue(0).rectifyLog(0).build();
        }
        int rectifyLog = workRectifyMapper.selectCount(new QueryWrapper<>());
        int running = Integer.parseInt(countRectifyRate.get("running").toString());
        int finish = Integer.parseInt(countRectifyRate.get("finish").toString());
        int overdue = Integer.parseInt(countRectifyRate.get("overdue").toString());
        int firstCheck = Integer.parseInt(countRectifyRate.get("firstCheck").toString());
        int inTime = Integer.parseInt(countRectifyRate.get("inTimeRate").toString());

        double rectifyRate = 0.0;
        double reportedRate = 0.0;
        double inTimeRate = 0.0;
        if ((running + finish) != 0) {
            rectifyRate = (double) finish / (running + finish) * 100;
            reportedRate = (double) firstCheck / (running + finish) * 100;
            inTimeRate = (double) inTime / (running + finish) * 100;
        }


        return WorkRectifyCountVO.builder()
                .rectifyLog(rectifyLog)
                .overdue(overdue)
                .finish(finish)
                .rectifyRate(new BigDecimal(rectifyRate).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())
                .reportedRate(new BigDecimal(reportedRate).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())
                .inTimeRate(new BigDecimal(inTimeRate).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())
                .effectiveRectify(running + finish).build();
    }

    /**
     * 地市级统计报表
     */
    public void countCity() {
        List<CityVO> cityVOS = cityService.list(10025);
        for (CityVO cityVO : cityVOS) {
            String cityName = cityVO.getName().substring(0, 2) + "分公司";
            QueryWrapper<WorkOrder> queryWrapper = new QueryWrapper();
            queryWrapper.select("vcYear as year", "count(*) as risk").eq("vcAuditUnit", cityName).eq("isDelete", 0).groupBy("vcYear");
            List<Map<String, Object>> maps = workOrderMapper.selectMaps(queryWrapper);
            List<WorkCountCity> list = new ArrayList<>();
            if (!CollectionUtils.isEmpty(maps)) {
                for (Map<String, Object> map : maps) {
                    //数据
                    Integer year = ObjectUtil.objToInteger(map.get("year"));
                    Integer risk = ObjectUtil.objToInteger(map.get("risk"));
                    Map<String, Object> countMap = workOrderMapper.countReport(year, cityName, null, null);
                    Integer rectify = null, notRectify = null, partRectify = null;
                    if (countMap != null) {
                        rectify = ObjectUtil.objToInteger(countMap.get("rectify"));
                        notRectify = ObjectUtil.objToInteger(countMap.get("notRectify"));
                        partRectify = ObjectUtil.objToInteger(countMap.get("partRectify"));
                    }
                    int notDateTime = workOrderMapper.selectCount(new QueryWrapper<WorkOrder>().eq("vcYear", year).eq("vcAuditUnit", cityName).eq("isDelete", 0).le("dtRectifyEndDate", new Date()));
                    Integer inTimeRate = workOrderMapper.inTimeRate(year, cityName, null, null);
                    //期数
                    String countPeriods = DateUtil.getReportPeriods();
                    list.add(WorkCountCity.builder().year(year).risk(risk).countPeriods(countPeriods)
                            .rectify(rectify).partRectify(partRectify).notRectify(notRectify)
                            .notDateTime(notDateTime).dateTime(ObjectUtil.calcPercent(inTimeRate, risk))
                            .updateTime(new Date()).company(cityVO.getName().substring(0, 2)).build());
                }
            }

            if (!CollectionUtils.isEmpty(list)) {
                workCountCityService.saveBatch(list);
            }
        }
    }

    /**
     * 省公司统计报表
     */
    public void countProvince() {
//        QueryWrapper<PUumOrganizationinfo> wrapper = new QueryWrapper<>();
//        wrapper.select("OULevel", "department", "departmentID").eq("company", "省公司").groupBy("departmentID");
//        List<Map<String, Object>> maps = commPUumOrganizationinfoService.listMaps(wrapper);
        QueryWrapper<WorkOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("vcWorkOrderDeptID","vcYear as year","COUNT(*) as risk").groupBy("vcWorkOrderDeptID","vcYear");
        List<Map<String, Object>> maps = workOrderMapper.selectMaps(queryWrapper);
        List<WorkCountProvince> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(maps)) {
            for (Map<String, Object> map : maps) {
                String departmentID = map.get("vcWorkOrderDeptID").toString();
                Integer year = ObjectUtil.objToInteger(map.get("year"));

                QueryWrapper<PUumOrganizationinfo> wrapper = new QueryWrapper<>();
                wrapper.select("department","departmentID").eq("departmentID",departmentID).groupBy("departmentID");
                Map<String, Object> pMap = commPUumOrganizationinfoService.getMap(wrapper);
                String department = pMap.get("department").toString();

                Map<String, Object> countMap = workOrderMapper.countReport(year, null, departmentID, null);
                Integer rectify = null, notRectify = null, partRectify = null;
                if (countMap != null) {
                    rectify = ObjectUtil.objToInteger(countMap.get("rectify"));
                    notRectify = ObjectUtil.objToInteger(countMap.get("notRectify"));
                    partRectify = ObjectUtil.objToInteger(countMap.get("partRectify"));
                }
                Integer risk = workOrderMapper.selectCount(new QueryWrapper<WorkOrder>().eq("vcYear",year).eq("vcWorkOrderDeptID", departmentID).eq("isDelete", 0));
                int notDateTime = workOrderMapper.selectCount(new QueryWrapper<WorkOrder>().eq("vcYear",year).eq("vcWorkOrderDeptID", departmentID).le("dtRectifyEndDate", new Date()));
                Integer inTimeRate = workOrderMapper.inTimeRate(year, null, departmentID, null);
                String countPeriods = DateUtil.getReportPeriods();
                list.add(WorkCountProvince.builder().risk(risk).countPeriods(countPeriods).departmentID(departmentID)
                        .rectify(rectify != null ? rectify : 0).partRectify(partRectify != null ? partRectify : 0).notRectify(notRectify != null ? notRectify : 0)
                        .notDateTime(notDateTime).dateTime(ObjectUtil.calcPercent(inTimeRate, risk))
                        .updateTime(new Date()).department(department).year(year).build());
            }
        }

        if (!CollectionUtils.isEmpty(list)) {
            workCountProvinceService.saveBatch(list);
        }
    }

    /**
     * 项目统计报表
     */
    public void countProject() {
        QueryWrapper<WorkOrder> wrapper = new QueryWrapper<>();
        wrapper.select("vcYear as year","vcItemName as itemName", "count(*) as risk").groupBy("vcItemName","vcYear");
        List<Map<String, Object>> maps = workOrderMapper.selectMaps(wrapper);
        List<WorkCountProject> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(maps)) {
            for (Map<String, Object> map : maps) {
                Integer year = ObjectUtil.objToInteger(map.get("year"));
                Integer risk = ObjectUtil.objToInteger(map.get("risk"));
                String itemName = map.get("itemName").toString();
                Map<String, Object> countMap = workOrderMapper.countReport(year, null, null, itemName);
                Integer rectify = null, notRectify = null, partRectify = null;
                if (countMap != null) {
                    rectify = ObjectUtil.objToInteger(countMap.get("rectify"));
                    notRectify = ObjectUtil.objToInteger(countMap.get("notRectify"));
                    partRectify = ObjectUtil.objToInteger(countMap.get("partRectify"));
                }
                int notDateTime = workOrderMapper.selectCount(new QueryWrapper<WorkOrder>().eq("vcItemName", itemName).eq("vcYear",year).eq("isDelete", 0).le("dtRectifyEndDate", new Date()));
                Integer inTimeRate = workOrderMapper.inTimeRate(year, null, null, itemName);
                String countPeriods = DateUtil.getReportPeriods();
                list.add(WorkCountProject.builder().risk(risk).countPeriods(countPeriods)
                        .rectify(rectify != null ? rectify : 0).partRectify(partRectify != null ? partRectify : 0).notRectify(notRectify != null ? notRectify : 0)
                        .notDateTime(notDateTime).dateTime(ObjectUtil.calcPercent(inTimeRate, risk))
                        .updateTime(new Date()).year(year).project(itemName).build());
            }
        }
        if (!CollectionUtils.isEmpty(list)) {
            workCountProjectService.saveBatch(list);
        }
    }


    public List<WorkCountReportVO> getCountReport(Integer type, Integer year, String city, String department, String itemName) {
        switch (type){
            case 1:
                return workOrderMapper.countCity(year,city);
            case 2:
                return workOrderMapper.countProvince(department);
            case 3:
                return workOrderMapper.countProject(year,itemName);
            default:
                throw new CustomParameterizedException("填写的统计类型不正确！");
        }
    }

    public void exportCityReport(Integer year, HttpServletResponse response) {
        //头文件
        List<String> header = Arrays.asList("涉及单位", "年份", "风险数量", "已整改", "未整改", "未到期", "到期整改率");
        List<WorkCountReportVO> list = workOrderMapper.countCity(year, null);
        //导出数据
        List<List<String>> contents = list.stream().map(vo ->
                Arrays.asList(vo.getName(), vo.getYear().toString(), vo.getRisk().toString(), vo.getRectify().toString(),
                        vo.getNotRectify().toString(),vo.getNotDateTime().toString(),vo.getDateTime().toString())
        ).collect(Collectors.toList());
        ExcelUtil.export("地市统计表", header, contents, response);
    }

    public void exportProvinceReport(HttpServletResponse response) {
        //头文件
        List<String> header = Arrays.asList("涉及单位", "风险数量", "已整改", "未整改", "未到期", "到期整改率");
        List<WorkCountReportVO> list = workOrderMapper.countProvince(null);
        //导出数据
        List<List<String>> contents = list.stream().map(vo ->
                Arrays.asList(vo.getName(), vo.getRisk().toString(), vo.getRectify().toString(),
                        vo.getNotRectify().toString(),vo.getNotDateTime().toString(),vo.getDateTime().toString())
        ).collect(Collectors.toList());
        ExcelUtil.export("省公司统计表", header, contents, response);
    }

    public void exportProjectReport(Integer year, HttpServletResponse response) {
        //头文件
        List<String> header = Arrays.asList("涉及单位", "年份", "风险数量", "已整改", "未整改", "未到期", "到期整改率");
        List<WorkCountReportVO> list = workOrderMapper.countProject(year, null);
        //导出数据
        List<List<String>> contents = list.stream().map(vo ->
                Arrays.asList(vo.getName(), vo.getYear().toString(), vo.getRisk().toString(), vo.getRectify().toString(),
                        vo.getNotRectify().toString(),vo.getNotDateTime().toString(),vo.getDateTime().toString())
        ).collect(Collectors.toList());
        ExcelUtil.export("项目整改率", header, contents, response);
    }

    public List<Map<String, Object>> getProvinceDept() {
        QueryWrapper<PUumOrganizationinfo> wrapper = new QueryWrapper<>();
        wrapper.select("department", "departmentID").eq("company", "省公司").groupBy("departmentID");
        return commPUumOrganizationinfoService.listMaps(wrapper);
    }

    public WorkRectify getByWorkId(Integer workId){
        return workRectifyMapper.selectOne(new QueryWrapper<WorkRectify>().eq("intWorkId",workId).orderByDesc("dtCreateTime").last("limit 1"));
    }

    public List<WorkRectify> list(Integer workId){
        List<WorkRectify> workRectifies = workRectifyMapper.selectList(new QueryWrapper<WorkRectify>().eq(workId != null, "intWorkId", workId));
        return workRectifies;
    }

    public void delete(Integer workId){
        workRectifyMapper.delete(new QueryWrapper<WorkRectify>().eq("intWorkId",workId));
    }
}
